
package com.common.android.utils.download;

/**   
 *    
 * @file 【下载安装服务】
 */
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Vector;
import java.util.zip.GZIPInputStream;

import org.apache.http.HttpException;
import org.apache.http.conn.ConnectTimeoutException;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.widget.RemoteViews;
import android.widget.Toast;

import com.common.android.utils.FileUtils;
import com.common.android.utils.ToastUtils;
import com.nd.android.u.allcommon.R;
import com.product.android.utils.LogUtils;

public class DownloadModule {
	private static final int PACKAGE_LENGH=4096;
	private static final int PROGRESS_DELTA=2;
    private static final int CONNECT_TIMEOUT = 20000; 	// 20秒
    private static final int READ_TIMEOUT = 30000;		// 30秒
    private static final String FILENAME_HEADER="filename=";
    private static final String TAG = "DownloadModule";
	private static final String CONFIG_NAME="download_config";
	private static final String RANGE = "Range";
    private static final String CONTENT_RANGE = "Content-Range";
    private static final String GZIP = "gzip";
    protected static final int DOWNLOAD_COMPLETE = 0;
    protected static final int DOWNLOAD_FAIL = 1;
    protected static final int ALREADY_EXIST = 2;
    protected static final int DOWNLOAD_PREPARE=3;
    protected static final int DOWNLOAD_PROGRESS=4;
    private static Vector<DownloadModule> mDownTasks;

    private static HashMap<Integer, DownloadModule> downTaskMap;


    private Context mContext;

    private String mSoftName = null;
    private String mSoftUrl;
    private int mAppId;
    private String mDownloadDirPath = null;
    private String mDownloadFileName;
    private int mDownloadIco = 0;
    private int mNotificationId = 0;
    
    // 文件存储
    private File mDownloadDir = null;
    private File mDownloadFile = null;

    // 通知栏
    private NotificationManager mNotificationManager = null;
    private Notification mNotification = null;

    // 通知栏跳转Intent
    private Intent downloadIntent = null;
    private Class<?> className;
    private PendingIntent mDownloadPendingIntent = null;

    private boolean isNuseProxy = false;
    private DownLoadData mDownLoadData;
    private SharedPreferences mPreferences;
    private long mStartPosition;
    private boolean isStop=false;
    private boolean isStarted=false;
    public DownloadModule(Context context) {
        mContext = context;
        mPreferences=context.getSharedPreferences(CONFIG_NAME, 0);
        mDownLoadData=new DownLoadData();
        mStartPosition=0;
        
    }

    public void setSoftName(String softName) {
        this.mSoftName = softName;
    }

    public void setSoftUrl(String softUrl) {
        this.mSoftUrl = softUrl;
    }

    public void setAppId(int appId) {
        this.mAppId = appId;
    }

    public void setDownloadDirPath(String downloadDirPath) {
        this.mDownloadDirPath = downloadDirPath;
    }

    public void setDownloadFileName(String downloadFileName) {
        this.mDownloadFileName = downloadFileName;
    }

    public void setDownloadIco(int downloadIco) {
        this.mDownloadIco = downloadIco;
    }

    public void setSoftUid(int notificationId) {
        this.mNotificationId = notificationId;
    }

    public void setNuseProxy(boolean isUseProxy) {
        this.isNuseProxy = isUseProxy;
    }

    public void setIntentClassName(Class<?> className) {
        this.className = className;
    }

    /**
     * @Title: getDownTaskCount
     * @Description: TODO(获取下载任务个数)
     * @author Administrator
     * @date 2012-3-1 上午11:30:31
     * @return
     * @return int
     * @throws
     */
    public static int getDownTaskCount() {
        if (mDownTasks != null) {
            return mDownTasks.size();
        } else {
            return 0;
        }
    }

    public static HashMap<Integer, DownloadModule> getDownTaskMap() {
        if (downTaskMap == null) {
            downTaskMap = new HashMap<Integer, DownloadModule>();
        }
        return downTaskMap;
    }

    private static void deleteDownTask(DownloadModule task) {
        if (mDownTasks != null) {
            mDownTasks.remove(task);
        }
    }

    private static void addDownTask(DownloadModule task) {
        if (mDownTasks == null) {
            mDownTasks = new Vector<DownloadModule>();
        }
        mDownTasks.add(task);
    }

    private static void deleteDownTaskFromMap(int appid) {
        if (downTaskMap != null) {
            downTaskMap.remove(appid);
        }
    }

    private static void addDownTaskToMap(int appid, DownloadModule task) {
        if (downTaskMap == null) {
            downTaskMap = new HashMap<Integer, DownloadModule>();
        }
        downTaskMap.put(appid, task);
    }

    public static String getSDPath() {
        File sdDir = null;
        // 判断sd卡是否存在
        boolean sdCardExist = Environment.getExternalStorageState().equals(
                android.os.Environment.MEDIA_MOUNTED);
        if (sdCardExist) {
            // 获取跟目录
            sdDir = Environment.getExternalStorageDirectory();
            return sdDir.toString();
        } else {
            // 返回到自己的默认安装路径
            return "";
        }

    }

    public void Start() {
        // 创建文件
        if (!checkSdCard()){
        	return;
        }
        Message msg=new Message();
        msg.what=DOWNLOAD_PREPARE;
        msg.arg1=0;
        downloadHandler.sendMessage(msg);
        // 开启一个新的线程下载，如果使用Service同步下载，会导致ANR问题，Service本身也会阻塞
        new Thread(new downloadRunnable()).start();
        addDownTask(DownloadModule.this);
        addDownTaskToMap(mAppId, DownloadModule.this);
    }
    
    public void startChapterDownload(){
        if (!checkSdCard()){
        	return;
        }
        new Thread(new Runnable() {
			public void run() {
				try {
					boolean isChatper=false;
					//获取服务端的文件名
					getDonwloadData(mSoftUrl,mDownLoadData);
					String webFileName = mDownLoadData.getServerFileName();
					if (webFileName != null) {
						//获取服务端文件名成功，直接服务端的文件名作为要下载的文件
			            mDownloadFileName = URLDecoder.decode(webFileName,"utf-8");
			        }
					mDownloadFile = new File(mDownloadDir.getPath(), mDownloadFileName);
					File[] files=mDownloadDir.listFiles();
					for (File file : files) {
						String name=file.getName();
						if (!name.equals(mDownloadFileName)){
							file.delete();
						}
					}
					String absoluteName=mDownloadFile.getAbsolutePath();
					mDownLoadData.setFileName(absoluteName);
					if (mDownloadFile!=null && mDownloadFile.exists()){
						//文件已存在
						long size=mDownloadFile.length();
						long serversize=mDownLoadData.getSize();
						if (serversize>0){
							//获取到服务端的文件大小
							if (size==serversize){
								//文件大小一致，认为是已经下载完成
								Message message = downloadHandler.obtainMessage();
								message.what=ALREADY_EXIST;
					            downloadHandler.sendMessage(message);
					            return;
							}
						}
					}
//					//检查配置文件里是否有保存该文件的信息
//					String downloadInfo=mPreferences.getString(absoluteName, "");
//					if (!TextUtils.isEmpty(downloadInfo)){
//						if (mDownLoadData.parseFromJSONString(downloadInfo)){
//							String url=mDownLoadData.getUrl();
//							if (url.equals(mSoftUrl) && mDownloadFile!=null && mDownloadFile.exists()){
//								int state=mDownLoadData.getState();
//								if (state==DownLoadData.SUCCESS){
//									//已下载成功，提示已下载
//									Message message = downloadHandler.obtainMessage();
//									message.what=ALREADY_EXIST;
//						            downloadHandler.sendMessage(message);
//						            return;
//								}else{
//									//下载未完成
//									long size=mDownloadFile.length();
//									if (size>0 && mDownLoadData.isChaterDownload()){
//										//允许断点续传
//										isChatper=true;	
//									}
//								}
//							}
//						}
//					}else{
//						if (mDownloadFile.exists()){
//							if (mDownloadFile.length()==mDownLoadData.getSize()){
//								//文件的大小和服务端返回来的大小一致，认为是下载完了
//								Message message = downloadHandler.obtainMessage();
//								message.what=ALREADY_EXIST;
//					            downloadHandler.sendMessage(message);
//					            return;
//							}
//						}
//					}
					Message message = downloadHandler.obtainMessage();
					message.what=DOWNLOAD_PREPARE;
					if (mDownLoadData.isChaterDownload()){
						message.arg1=(int)(mDownloadFile.length()*100/mDownLoadData.getSize());
						downloadHandler.sendMessage(message);
						doChaterDownload(mDownLoadData);
					}else{
						downloadHandler.sendMessage(message);
						doDownload(mDownLoadData);
					}
				} catch (Exception e) {
		            // 下载失败
					String error=e.getMessage();
					Message message = downloadHandler.obtainMessage();
					message.what=DOWNLOAD_FAIL;
					message.obj=error;
		            downloadHandler.sendMessage(message);	
				}
			}
		}).start();
    }
    
    private boolean checkSdCard(){
    	String strSdPath = getSDPath();
        if (strSdPath.length() > 0) {
            mDownloadDir = new File(strSdPath+File.separator+mDownloadDirPath);
            if (!mDownloadDir.exists()) {
                mDownloadDir.mkdirs();
            }
        } else {
            Toast.makeText(mContext, R.string.no_sdcard_for_download, Toast.LENGTH_LONG).show();
            return false;
        }
        return true;
    }

    void InitNotificationView(int startValue) {
        // 使用notification.xml文件作VIEW
        mNotification.contentView.setProgressBar(R.id.download_notification_down_progress_bar, 100,startValue, false);
        mNotification.contentView.setTextViewText(R.id.download_notification_down_progress, startValue+"%");
        mNotification.contentView.setTextViewText(R.id.download_notification_soft, mSoftName);
        mNotification.contentView.setViewVisibility(R.id.download_notification_progressblock,View.VISIBLE);
        mNotification.contentView.setImageViewResource(R.id.imgV_ico, mDownloadIco);
        mNotification.contentIntent = mDownloadPendingIntent;

        // 打开软件时，系统会自动检测升级，有新版本会发送一条id=1的知在通知栏里，先结束掉，这样就不会出现两条提示通知
        mNotificationManager.cancel(1);
        // 发出通知
        mNotificationManager.notify(mNotificationId, mNotification);
    }

    // 下载线程
    //
    class downloadRunnable implements Runnable {

        Message message = downloadHandler.obtainMessage();

        public void run() {
            message.what = DOWNLOAD_COMPLETE;

            try {
                // 增加权限<uses-permission
                // android:name="android.permission.WRITE_EXTERNAL_STORAGE">;
                String webFileName = getFilename(mSoftUrl);
                if (webFileName != null) {
                    mDownloadFileName = URLDecoder.decode(webFileName,"utf-8");
                }
                mDownloadFile = new File(mDownloadDir.getPath(), mDownloadFileName);

                if (!mDownloadFile.exists()) {
                    mDownloadFile.createNewFile();
                }

                // 下载函数
                // 增加权限<uses-permission
                // android:name="android.permission.INTERNET">;
                long downloadSize = downloadFile(mSoftUrl, mDownloadFile);
                if (downloadSize > 0) {
                    // 下载成功
                    downloadHandler.sendMessage(message);
                }

            } catch (Exception ex) {
                ex.printStackTrace();
                message.what = DOWNLOAD_FAIL;
                // 下载失败
                downloadHandler.sendMessage(message);
            }
        }
    }

    // 下载结果处理
    private Handler downloadHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {

            switch (msg.what) {
            	case DOWNLOAD_PREPARE:
            		//arg1放着当前的进度
            		int startValue=msg.arg1;
            		// 设置下载过程中，点击通知栏，回到主界面
                    if (null == className) {
                        // 下载过程点击通知栏消息，收起通知栏，不跳转
                        downloadIntent = new Intent();
                    } else {
                        downloadIntent = new Intent(mContext, className);
                        downloadIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
                    }
                    String title=mSoftName+ mContext.getResources().getString(R.string.start_download);
                    mNotification = new Notification(mDownloadIco,title ,System.currentTimeMillis());
                    mDownloadPendingIntent = PendingIntent.getActivity(mContext, 1, downloadIntent,PendingIntent.FLAG_UPDATE_CURRENT);
                    mNotificationManager = (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
                    mNotification.contentView = new RemoteViews(mContext.getPackageName(), R.layout.notification);
                    InitNotificationView(startValue);
                    addDownTask(DownloadModule.this);
			        addDownTaskToMap(mAppId, DownloadModule.this);
			        saveConfig(DownLoadData.TO_START);
			        isStarted=true;
            		break;
            	case DOWNLOAD_PROGRESS:
            		//改变进度
            		int iProgress=msg.arg1;
            		mNotification.contentView.setProgressBar(R.id.download_notification_down_progress_bar, 100, iProgress, false);
                    mNotification.contentView.setTextViewText(R.id.download_notification_down_progress, iProgress + "%");
                    mNotificationManager.notify(mNotificationId, mNotification);
            		break;
                case DOWNLOAD_COMPLETE:
                	isStarted=false;
                	mNotification.contentView.setViewVisibility(R.id.download_notification_progressblock,View.GONE);
                    deleteDownTask(DownloadModule.this);
                    deleteDownTaskFromMap(mAppId);

                    // 点击安装PendingIntent
                    Uri uri = Uri.fromFile(mDownloadFile);
                    Intent installIntent = new Intent(Intent.ACTION_VIEW);
                    installIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
                            | Intent.FLAG_ACTIVITY_NEW_TASK);
                    String sURIType = getURIType(mDownloadFileName);
                    if (sURIType == null) {
                        // 下载失败
                        mNotification.contentView.setTextViewText(
                                R.id.download_notification_down_progress, mContext.getResources().getString(R.string.canot_identify_file_type));
                        mNotificationManager.notify(mNotificationId, mNotification);
                        break;
                    }
                    installIntent.setDataAndType(uri, sURIType);

                    mDownloadPendingIntent = PendingIntent
                            .getActivity(mContext, 0, installIntent, 0);
                    mNotification.contentView.setTextViewText(
                            R.id.download_notification_down_progress, mContext.getResources().getString(R.string.click_after_download));
                    mNotification.contentIntent = mDownloadPendingIntent;
                    mNotification.tickerText = mSoftName + mContext.getResources().getString(R.string.download_finish);
                    mNotification.flags |= Notification.FLAG_AUTO_CANCEL;
                    mNotificationManager.notify(mNotificationId, mNotification);
                    try {
                        mContext.startActivity(installIntent);
                    } catch (ActivityNotFoundException e) {
                        mNotification.contentView.setTextViewText(
                                R.id.download_notification_down_progress, mContext.getResources().getString(R.string.no_app_to_open_file));
                        mNotificationManager.notify(mNotificationId, mNotification);
                    }
                    saveConfig(DownLoadData.SUCCESS);
                    break;
                case DOWNLOAD_FAIL:
                    // 下载失败
                    deleteDownTask(DownloadModule.this);
                    deleteDownTaskFromMap(mAppId);
                    String errormsg=(String)msg.obj;
                    if (TextUtils.isEmpty(errormsg)){
                    	errormsg=mContext.getResources().getString(R.string.reload_after_download_fail);
                    }else{
                    	errormsg=mContext.getResources().getString(R.string.reload_after_download_fail)+(errormsg);
                    }
                    if (!isStarted){
                    	ToastUtils.display(mContext,errormsg);
                    	return;
                    }
                    isStarted=false;
                    if (mNotification==null){
                    	return;
                    }
                    mNotification.contentView.setViewVisibility(R.id.download_notification_progressblock,View.GONE);
                    mNotification.contentView.setTextViewText(R.id.download_notification_down_progress, errormsg);
                    mNotificationManager.notify(mNotificationId, mNotification);
                	saveConfig(DownLoadData.FAIL);
                    break;
                case ALREADY_EXIST:
                	//已经存在
                	isStarted=false;
                	AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
            		builder.setTitle(R.string.file_exists);
            		builder.setMessage(mContext.getResources().getString(R.string.your_operation));
            		builder.setNeutralButton(R.string.redownload, new Dialog.OnClickListener() {
            			@Override
            			public void onClick(DialogInterface dialog, int which) {
            				dialog.dismiss();
            				mDownloadFile.delete();
            				try {
								mDownloadFile.createNewFile();
								Message message = downloadHandler.obtainMessage();
								message.what=DOWNLOAD_PREPARE;
								downloadHandler.sendMessage(message);
								new Thread(new Runnable() {
									public void run() {
										if (mDownLoadData.isChaterDownload()){
											//可以断点续传
											doChaterDownload(mDownLoadData);	
										}else{
											doDownload(mDownLoadData);
										}
									}
								}).start();
							} catch (IOException e) {
								e.printStackTrace();
							}
            				
            			}
            		});
            		builder.setPositiveButton(R.string.install_now, new Dialog.OnClickListener() {
            			@Override
            			public void onClick(DialogInterface dialog, int which) {
            				dialog.dismiss();
            				String sURIType = getURIType(mDownloadFileName);
                            if (sURIType == null) {
                                // 无法识别的文件
                            	ToastUtils.display(mContext, R.string.canot_identify_file_type);
                                return;
                            }
            				Uri uri = Uri.fromFile(mDownloadFile);
                            Intent installIntent = new Intent(Intent.ACTION_VIEW);
                            installIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP| Intent.FLAG_ACTIVITY_NEW_TASK);
                            installIntent.setDataAndType(uri, sURIType);
                            mContext.startActivity(installIntent);
            			}
            		});
            		AlertDialog dialog = builder.create();
            		dialog.show();
                	break;
                default:
                    break;
            }
        }
    };

    private void saveConfig(int type){
    	if (mDownLoadData.isChaterDownload()){
    		String info=mDownLoadData.toJSONString();
        	if (!TextUtils.isEmpty(info)){
        		mPreferences.edit().putString(mDownLoadData.getFileName(), info).commit();
        	}	
    	}
    }
    
    /**
     * @brief 【获取URI类型】
     * @n<b>函数名称</b> :getURIType
     * @param sFileName
     * @return
     * @return String
     */
    protected String getURIType(String sFileName) {
        int iIndex = sFileName.lastIndexOf('.');
        if (iIndex < 0) {
            // 找不到后缀时返回null
            return null;
        }
        String sType = sFileName.substring(iIndex + 1);
        sType.toLowerCase();
        // 建立一个MIME类型与文件后缀名的匹配表
		final String[][] MIME_MapTable = {
				// {后缀名， MIME类型}
				{ "3gp", "video/3gpp" }, { "7z", "application/x-compress" },
				{ "apk", "application/vnd.android.package-archive" },
				{ "asf", "video/x-ms-asf" }, { "avi", "video/x-msvideo" },
				{ "bin", "application/octet-stream" }, { "bmp", "image/bmp" },
				{ "c", "text/plain" }, { "class", "application/octet-stream" },
				{ "conf", "text/plain" }, { "cpp", "text/plain" },
				{ "doc", "application/msword" },
				{ "docx", "application/msword" },
				{ "exe", "application/octet-stream" }, { "gif", "image/gif" },
				{ "gtar", "application/x-gtar" },
				{ "gz", "application/x-gzip" }, { "h", "text/plain" },
				{ "htm", "text/html" }, { "html", "text/html" },
				{ "jar", "application/java-archive" },
				{ "java", "text/plain" }, { "jpeg", "image/jpeg" },
				{ "jpg", "image/jpeg" }, { "js", "application/x-javascript" },
				{ "log", "text/plain" }, { "m3u", "audio/x-mpegurl" },
				{ "m4a", "audio/mp4a-latm" }, { "m4b", "audio/mp4a-latm" },
				{ "m4p", "audio/mp4a-latm" }, { "m4u", "video/vnd.mpegurl" },
				{ "m4v", "video/x-m4v" }, { "mov", "video/quicktime" },
				{ "mp2", "audio/x-mpeg" }, { "mp3", "audio/x-mpeg" },
				{ "mp4", "video/mp4" },
				{ "mpc", "application/vnd.mpohun.certificate" },
				{ "mpe", "video/mpeg" }, { "mpeg", "video/mpeg" },
				{ "mpg", "video/mpeg" }, { "mpg4", "video/mp4" },
				{ "mpga", "audio/mpeg" },
				{ "msg", "application/vnd.ms-outlook" },
				{ "ogg", "audio/ogg" }, { "pdf", "application/pdf" },
				{ "png", "image/png" }, { "psd", "image/x-photoshop" },
				{ "pps", "application/vnd.ms-powerpoint" },
				{ "ppt", "application/vnd.ms-powerpoint" },
				{ "pptx", "application/vnd.ms-powerpoint" },
				{ "prop", "text/plain" },
				{ "rar", "application/x-rar-compressed" },
				{ "rc", "text/plain" }, { "rmvb", "audio/x-pn-realaudio" },
				{ "rtf", "application/rtf" }, { "sh", "text/plain" },
				{ "tar", "application/x-tar" },
				{ "tgz", "application/x-compressed" },
				{ "txt", "text/plain" },
				{ "wav", "audio/x-wav" },
				{ "wma", "audio/x-ms-wma" },
				{ "wmv", "audio/x-ms-wmv" },
				{ "wps", "application/vnd.ms-works" },
				// {"xml", "text/xml"},
				{ "xml", "text/plain" }, { "xls", "application/vnd.ms-excel" },
				{ "xlsx", "application/vnd.ms-excel" },
				{ "z", "application/x-compress" },
				{ "zip", "application/zip" }, { "", "*/*" } };
        String sURIType = null;
        for (int i = 0; i < MIME_MapTable.length; i++) {
            if (sType.equals(MIME_MapTable[i][0]))
                sURIType = MIME_MapTable[i][1];
        }
        return sURIType;
    }

    /**
     * @brief 【下载文件】
     * @n<b>函数名称</b> :downloadFile
     * @param downloadUrl
     * @param saveFile
     * @return
     * @throws Exception
     * @return long
     */
    public long downloadFile(String downloadUrl, File saveFile) throws Exception {
    	int downloadCount = 0;
        int currentSize = 0;
        long totalSize = 0;
        long updateTotalSize = 0;

        HttpURLConnection httpConnection = null;
        InputStream is = null;
        FileOutputStream fos = null;

//        InitNotificationView();

        try {

            URL url = new URL(downloadUrl);

            // 有代理则使用代理，否则就是网络问题
            if (!isNuseProxy) {
                Proxy proxy = GetProxy();
                if (proxy != null) {
                    httpConnection = (HttpURLConnection)url.openConnection(proxy);
                } else {
                    httpConnection = (HttpURLConnection)url.openConnection();
                }
            } else {
                httpConnection = (HttpURLConnection)url.openConnection();
            }
            if (currentSize > 0) {
                httpConnection.setRequestProperty("RANGE", "bytes=" + currentSize + "-");
            } else {
                httpConnection.setRequestProperty("RANGE", "bytes=0-");
            }

            httpConnection.setConnectTimeout(10000);
            httpConnection.setReadTimeout(20000);
            updateTotalSize = httpConnection.getContentLength();
            if (updateTotalSize < 1) {
                String sLength = httpConnection.getHeaderField("Content-Range");
                if (null != sLength) { // 支持断点
                    updateTotalSize = getTotalLength(sLength);
                }
            }
            if (httpConnection.getResponseCode() == 404) {
                throw new Exception("fail!");
            }

            is = httpConnection.getInputStream();
            fos = new FileOutputStream(saveFile, false);
            byte buffer[] = new byte[4096];
            int readsize = 0;

            while ((readsize = is.read(buffer)) > 0) {
                fos.write(buffer, 0, readsize);
                totalSize += readsize;
                int iProgress = (int)(totalSize * 100 / updateTotalSize);

                // 为了防止频繁的通知导致应用吃紧，百分比增加10才通知一次
                if ((downloadCount == 0) || (iProgress - PROGRESS_DELTA) >= downloadCount) {
                    downloadCount=iProgress;
                    Message msg=new Message();
                    msg.what=DOWNLOAD_PROGRESS;
                    msg.arg1=iProgress;
                    downloadHandler.sendMessage(msg);
                }
            }
            Message msg=new Message();
            msg.what=DOWNLOAD_COMPLETE;
            downloadHandler.sendMessage(msg);
        } finally {
            if (httpConnection != null) {
                httpConnection.disconnect();
            }
            if (is != null) {
                is.close();
            }
            if (fos != null) {
                fos.close();
            }
        }
        return totalSize;
    }

    /**
     * @brief 【获取文件名】
     * @n<b>函数名称</b> :downloadFile
     * @param downloadUrl
     * @param saveFile
     * @return
     * @throws Exception
     * @return long
     */
    public String getFilename(String downloadUrl) throws Exception {

        HttpURLConnection httpConnection = null;

        try {

            URL url = new URL(downloadUrl);

            // 有代理则使用代理，否则就是网络问题
            if (!isNuseProxy) {
                Proxy proxy = GetProxy();
                if (proxy != null) {
                    httpConnection = (HttpURLConnection)url.openConnection(proxy);
                } else {
                    httpConnection = (HttpURLConnection)url.openConnection();
                }
            } else {
                httpConnection = (HttpURLConnection)url.openConnection();
            }
            httpConnection.setRequestProperty("RANGE", "bytes=0-0");

            httpConnection.setConnectTimeout(10000);
            httpConnection.setReadTimeout(20000);
            String sFileNameHeader = httpConnection.getHeaderField("Content-Disposition");

            if (httpConnection.getResponseCode() == 404) {
                throw new Exception("fail!");
            }
            if (sFileNameHeader == null) {
                return getFileNameFromUrl(downloadUrl);
            }
            
            sFileNameHeader = new String(sFileNameHeader.getBytes("ISO-8859-1"), "utf-8");
            int nIndex = sFileNameHeader.indexOf("filename=");
            if (nIndex < 0) {
                return null;
            }
            String sFileName = sFileNameHeader.substring(nIndex + 9);
            nIndex=sFileName.indexOf(";");
            if (nIndex>0){
            	sFileName=sFileName.substring(0,nIndex);
            }
            nIndex = sFileName.indexOf('"');
            if (nIndex < 0) {
                // 文件名没有用引号包起来的情况
                return sFileName;
            }
            sFileName = sFileName.substring(nIndex + 1);
            nIndex = sFileName.indexOf('"');
            if (nIndex < 0) {
                // 文件名用引号包起来的情况，需要成对出现
                return null;
            }
            sFileName = sFileName.substring(0, nIndex);
            return sFileName;
        } finally {
            if (httpConnection != null) {
                httpConnection.disconnect();
            }
        }
    }

    /**
     * @param sContent 从http头取得的"Content-Range"字段
     * @return >0 表示成功，小于等于0表示失败
     */
    protected static long getTotalLength(String sContent) {
        try {
            int nIndex = sContent.indexOf('/');
            String sTotal = sContent.substring(nIndex + 1);
            long nTotal = Long.parseLong(sTotal, 10);
            return nTotal;
        } catch (Exception e) {

        }
        return 0;
    }

    static Proxy GetProxy() {
        Proxy proxy = null;
        if (android.net.Proxy.getDefaultHost() != null) {
            proxy = new Proxy(java.net.Proxy.Type.HTTP,
                    new InetSocketAddress(android.net.Proxy.getDefaultHost(),
                            android.net.Proxy.getDefaultPort()));
        }

        return proxy;
    }
    
    private void getDonwloadData(String downloadUrl,DownLoadData data) throws MalformedURLException,IOException, HttpException{
    	URL url = new URL(downloadUrl);
    	data.setUrl(downloadUrl);
    	HttpURLConnection httpConnection=(HttpURLConnection)url.openConnection();
        httpConnection.setRequestProperty("RANGE", "bytes=0-0");
        httpConnection.setConnectTimeout(10000);
        httpConnection.setReadTimeout(20000);
        String sFileNameHeader = httpConnection.getHeaderField("Content-Disposition");
        int code=httpConnection.getResponseCode();
        if (code!=200 &&code!=206){
            throw new HttpException("connect fail("+code+"):"+httpConnection.getResponseMessage());
        }
        sFileNameHeader = new String(sFileNameHeader.getBytes("ISO-8859-1"), "utf-8");
        //获取服务端文件名
        String serverFileName="";
        if (!TextUtils.isEmpty(sFileNameHeader)) {
            //
        	int nIndex = sFileNameHeader.indexOf(FILENAME_HEADER);
            if (nIndex >= 0) {
            	String sFileName = sFileNameHeader.substring(nIndex + FILENAME_HEADER.length());
                nIndex = sFileName.indexOf('"');
                if (nIndex < 0) {
                    // 文件名没有用引号包起来的情况
                	serverFileName=sFileName;
                }else{
                	sFileName = sFileName.substring(nIndex + 1);
                    nIndex = sFileName.indexOf('"');
                    if (nIndex > 0) {
                        // 文件名用引号包起来的情况，需要成对出现
                    	serverFileName = sFileName.substring(0, nIndex);
                    }
                }
            }
        }
        data.setServerFileName(serverFileName);
        //获取文件长度以及是否允许断点续传
        String sLen=httpConnection.getHeaderField(CONTENT_RANGE);
        if (TextUtils.isEmpty(sLen)){
        	data.setIsChaterDownload(false);
        }else{
        	data.setIsChaterDownload(true);
        	long size=getTotalLength(sLen);
        	data.setSize(size);
        }
    }
    
    public void doDownload(DownLoadData data){
    	int downloadCount = 0;
    	File file=new File(data.getFileName());
    	File saveFile=new File(data.getFileName()+"temp");
        long receivedSize=0;
        long updateTotalSize = data.getSize();
        HttpURLConnection httpConnection = null;
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            URL url = new URL(data.getUrl());
            httpConnection = (HttpURLConnection)url.openConnection();
            httpConnection.setRequestProperty("RANGE", "bytes=0-");
            httpConnection.setConnectTimeout(10000);
            httpConnection.setReadTimeout(20000);
            if (httpConnection.getResponseCode() == 404) {
                throw new Exception("fail!");
            }
            if (updateTotalSize<=0){
            	updateTotalSize = httpConnection.getContentLength();
                if (updateTotalSize < 1) {
                    String sLength = httpConnection.getHeaderField("Content-Range");
                    if (null != sLength) {
                        updateTotalSize = getTotalLength(sLength);
                    }
                }
            }
            is = httpConnection.getInputStream();
            fos = new FileOutputStream(saveFile, false);
            byte buffer[] = new byte[4096];
            int readsize = 0;
            while ((readsize = is.read(buffer)) > 0) {
                fos.write(buffer, 0, readsize);
                receivedSize += readsize;
                int iProgress = (int)(receivedSize * 100 / updateTotalSize);

                // 为了防止频繁的通知导致应用吃紧，百分比增加10才通知一次
                if ((downloadCount == 0) || (iProgress - PROGRESS_DELTA) >= downloadCount) {
                	Message msg=new Message();
                    downloadCount=iProgress;
                    msg.what=DOWNLOAD_PROGRESS;
                    msg.arg1=iProgress;
                    downloadHandler.sendMessage(msg);
                }
            }
            FileUtils.copyFile(saveFile, file);
            saveFile.delete();
            Message msg=new Message();
            msg.what=DOWNLOAD_COMPLETE;
            downloadHandler.sendMessage(msg);
            return;
        } catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
            if (httpConnection != null) {
                httpConnection.disconnect();
            }
            try {
            	if (is != null) {
                    is.close();
                }
                if (fos != null) {
                    fos.close();
                }	
			} catch (Exception e2) {
			}
        }
        Message msg=new Message();
        msg.what=DOWNLOAD_FAIL;
        downloadHandler.sendMessage(msg);
    }
    
    public void doChaterDownload(DownLoadData data) {
    	LogUtils.d("debug", "doChaterDownload");
        InputStream inputStream = null;
        OutputStream os = null;
        byte buf[] = new byte[PACKAGE_LENGH];
        File file=new File(data.getFileName());
        String url=data.getUrl();
        int byteread;
        long lOffset;
        long lTotal = 0;
        HttpURLConnection conn = null;
        try {
                lOffset = file.length();
                URL fileURL = new URL(url);
                conn = (HttpURLConnection) fileURL.openConnection();
                // conn.setAllowUserInteraction(true);
                conn.setRequestProperty(RANGE, "bytes=" + lOffset + "-");
                conn.setConnectTimeout(CONNECT_TIMEOUT);
                conn.setReadTimeout(READ_TIMEOUT);

                String sLength = conn.getHeaderField(CONTENT_RANGE);
                lTotal = getTotalLength(sLength);
                os = new FileOutputStream(file, true);
                inputStream = conn.getInputStream();
                String contentEncoding = conn.getContentEncoding();
                // 判断是否有压缩
                if (contentEncoding != null && contentEncoding.equalsIgnoreCase(GZIP)) {
                    inputStream = new GZIPInputStream(inputStream);
                }
                long progressd=lOffset;
                long progress_delta=getProgressDelta(lTotal);
                while ((byteread = inputStream.read(buf)) != -1) {
//                	Log.d("debug", byteread+"");
                    if (lOffset < lTotal) {
                        if (isStop) {
                        	LogUtils.d("debug", "chapter download stop");        	
                            // 取消下载
                            if (inputStream != null) {
                                try {
                                    inputStream.close();
                                } catch (IOException ioe) {
                                    LogUtils.e(TAG, ioe.toString());
                                }
                            }
                        }
                    }
                    os.write(buf, 0, byteread);
                    lOffset += byteread;
                    if (lOffset-progressd>progress_delta){
                        // 进度反馈
                        Message msg=new Message();
                        msg.what=DOWNLOAD_PROGRESS;
                        msg.arg1=(int) (lOffset*100/lTotal);
                        downloadHandler.sendMessage(msg);
                        progressd=lOffset;
                    }
                }
                Message msg=new Message();
                msg.what=DOWNLOAD_COMPLETE;
                downloadHandler.sendMessage(msg);
                return;
        } catch (SocketTimeoutException e) {
            LogUtils.e(TAG, e.toString());
        } catch (SocketException e) {
            LogUtils.e(TAG, e.toString());
        } catch (ConnectTimeoutException e) {
            LogUtils.e(TAG, e.toString());
        } catch (UnknownHostException e) {
            LogUtils.e(TAG, e.toString());
        } catch (Exception e) {
            LogUtils.e(TAG, e.toString());
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException ioe) {
                    LogUtils.e(TAG, ioe.toString());
                }
            }
            if (null != os) {
                try {
                    os.close();
                } catch (IOException ioe) {
                    LogUtils.e(TAG, ioe.toString());
                }
            }
        }
        Message msg=new Message();
        msg.what=DOWNLOAD_FAIL;
        downloadHandler.sendMessage(msg);
    }
    
    public void stopCurrent(){
    	if (mDownLoadData!=null){
    		if (mDownLoadData.isChaterDownload()){
    			isStop=true;
    		}
    	}
    }
    
    public boolean isDownloading(){
    	return isStarted;
    }
    
    private long getProgressDelta(long size){
    	if (size>4194304){
    		return size/100;
    	}else{
    		return size/50;
    	}
    }
    
    public String getFileNameFromUrl(String url){
    	int index = url.lastIndexOf("/", url.length());
    	return url.substring(index+1, url.length());
    }
}
